import { isPostTimeFrame, waitForSelectorWithInterval, arrayToValueOfConfig, replacePlaceholder, closeUnwantedPages } from "../../utils/index.js"
import { configMap, createNamedStore } from "../../config/index.js"
import CryptoJS from "crypto-js"
import { isPostCommented, savePostData } from "../../api/webApi/index.js"
// 创建本地缓存存储实例用于记录评论任务运行周期
export const commentCycleStore = createNamedStore("comment-cycles")
export async function td_posting_comment_main(task, browser, index, taskId, collectPlatformParams) {
  const composedTask = task.composedTask
  // 当前策略的运行时间段
  const ranges = task?.operatingTimeRanges?.ranges || []
  console.log("td_posting_comment_main=ranges===>", ranges)
  // 创建结果对象
  const result = {
    success: false,
    message: "",
    taskId,
    commentedCount: 0,
  }

  let timeOfText = {
    [0]: "处理全部帖子",
    [1]: "处理最近3天的帖子",
    [2]: "处理近一周帖子",
    [3]: "处理近俩周帖子",
  }
  // 已经处理过的文案不再处理。记录一下
  let isHandleList = []
  // 汇总数据
  let postDataTotal = []
  // 是否已完成
  let finished = false
  // 最后一条已处理过的帖子
  let lastHandlePost = null
  // 获取配置参数
  // 获取运行配置
  const config = composedTask.config || []
  // 评论内容
  const _comment = arrayToValueOfConfig(config, "comment")
  // 曝光量范围
  const _amountOfExposure = Number(arrayToValueOfConfig(config, "amount_of_exposure"))
  // 点赞量范围
  const _likeCount = Number(arrayToValueOfConfig(config, "like_count"))
  // 是否置顶帖子
  const _topPost = arrayToValueOfConfig(config, "top_post")
  // 评论帖子的时间范围
  const _timeFrame = arrayToValueOfConfig(config, "time_frame")
  // 获取运行周期  1每天运行一次  2每次任务时间段内执行一次
  const _runCycle = arrayToValueOfConfig(config, "execution_cycle")
  // 获取自定义时间段配置（可选，格式为 "18:00-18:30,18:31-19:00"）
  const _customTimeSlots = arrayToValueOfConfig(config, "custom_time_slots")

  // 检查运行周期条件是否满足
  const accountId = task.platformAccount
  const cacheKey = `threads_comment_${accountId}`
  const lastCommentTime = commentCycleStore.get(cacheKey)
  console.log("lastCommentTime===>", lastCommentTime)
  const currentTime = Date.now()

  console.log(`当前运行周期: ${_runCycle === "1" ? "每天运行一次" : "每次任务时间段内执行一次"}`)

  // 判断是否满足运行条件
  const isSatisfiedRunCycle = await isInConditionsAsync(lastCommentTime, currentTime, ranges, commentCycleStore, cacheKey, _runCycle)
  if (isSatisfiedRunCycle) {
    console.log("跳过执行，原因：====>isSatisfiedRunCycle", isSatisfiedRunCycle)
    return
  }
  // 记录当前运行时间
  console.log(`满足运行条件，开始执行评论任务，更新运行时间: ${new Date(currentTime).toLocaleString()}`)

  // 转换评论内容
  console.log("task=>=====>", task)
  const commentText = replacePlaceholder(_comment, configMap, task)
  // 解构task获取必要参数，兼容新旧格式
  const {
    threadsDomain = "https://www.threads.net", // Threads网站域名
  } = task || {}
  // 收集指定账号的帖子信息
  // 开始数据处理
  console.log(`开始处理账号(${index + 1}): ${task.account}`)
  await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 10))
  await closeUnwantedPages(browser, ["www.threads.net", "start.adspower.net"])
  const page = await browser.newPage()
  await page.setViewport({ width: 1920, height: 1080 })
  console.log("我进来找帖子数据了！=====>")
  try {
    await page.goto(threadsDomain, { waitUntil: "networkidle2" })
    await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 5))

    // 获取主页按钮
    const profileButtonSelector = ".x1n2onr6:nth-child(5) .xefz13k"
    await page.waitForSelector(profileButtonSelector, { timeout: 10000 })
    const profileButton = await page.$(profileButtonSelector)
    console.log("个人主页按钮=====>", profileButton)

    if (profileButton) {
      // 点击搜索按钮后等待页面跳转加载
      await Promise.all([
        profileButton.click(),
        page.waitForNavigation({ waitUntil: "networkidle0" }), // 等待页面完全加载
      ])
    } else {
      console.log("按钮没有找到")
    }

    // 等待输入框出现
    const nickNameSelector = "h1.x133cpev"
    await page.waitForSelector(nickNameSelector, { timeout: 10000 })

    // 获取输入框的位置信息
    const nickNameBox = await page.$(nickNameSelector)
    const nickNameBoxPosition = await nickNameBox.boundingBox()

    if (nickNameBoxPosition) {
      const postSelector = ".x1e4zzel > .x78zum5 > div"
      console.log("搜索完成！,等待页面接口响应")
      let followedCount = 0
      // 等待顶部用户信息列表出现
      await page.waitForSelector('div[class="x6s0dn4 x40hh3e xrvj5dj xxfwaov"]', { timeout: 15 * 1000 })
      // 获取控件
      const userListElement = await page.$('div[class="x6s0dn4 x40hh3e xrvj5dj xxfwaov"]')
      // 获取里面昵称文本
      const userTextElement = await userListElement.$(
        'h1[class="x1lliihq x1plvlek xryxfnj x1n2onr6 x1ji0vk5 x18bv5gf x193iq5w xeuugli x1fj9vlw x13faqbe x1vvkbs x1s928wv xhkezso x1gmr53x x1cpjm7i x1fgarty x1943h6x x1i0vuye x133cpev x1xlr1w8 xp07o12 x1yc453h"]'
      )
      const userText = await page.evaluate((el) => el.textContent.trim(), userTextElement)
      console.log(`当前用户昵称: ${userText}`)
      // 获取用户账号
      const userAccountText = await userListElement.$('span[class="x1lliihq x193iq5w x6ikm8r x10wlt62 xlyipyv xuxw1ft"]')
      const userAccount = await page.evaluate((el) => el.textContent.trim(), userAccountText)
      console.log(`当前用户账号: ${userAccount}`)
      // 获取粉丝数量父节点
      const followedCountParentElement = await page.$('div[class="x6s0dn4 x78zum5 x14vqqas xu0aao5"]')
      // 获取粉丝数量
      const followedCountElement = await followedCountParentElement.$(".x6s0dn4 > .x12rw4y6 > span")
      followedCount = followedCountElement ? await page.evaluate((el) => el.textContent.trim(), followedCountElement) : 0
      console.log(`粉丝数量: ${followedCount}`)
      // 我进来找帖子了！
      console.log("我进来找帖子了！")
      // 等待 postSelector 出现
      await page.waitForSelector(postSelector, { timeout: 10000 })
      while (!finished) {
        // 获取帖子列表
        let postList = await page.$$(postSelector)
        let visiblePosts = []

        for (const post of postList) {
          const box = await post.boundingBox()
          if (box) {
            visiblePosts.push(post)
          }
        }
        console.log(`当前页面找到 ${visiblePosts.length} 个可见帖子`)

        // 记录当前循环开始前的帖子数量
        const startingHandledCount = isHandleList.length
        let processedAnyNewPost = false

        for (let index = 0; index < visiblePosts.length; index++) {
          try {
            console.log(`----- 开始处理第${index + 1}/${visiblePosts.length}个帖子 -----`)
            let postData = {
              platformAccount: "",
              author: userText || "",
              caption: "",
              like_count: 0,
              direct_reply_count: 0,
              impression_count: 0,
              repost_count: 0,
              reshare_count: 0,
              followedCount: 0,
              date: "",
            }
            const visiblePost = visiblePosts[index]
            // 获取元素的位置
            const boundingBox = await visiblePost.boundingBox()

            // 记录处理帖子前的滚动位置
            const beforePostScrollPosition = await page.evaluate(() => window.scrollY)

            // 先获取帖子文案和作者信息，判断是否已处理过，避免不必要的滚动
            const selectors = [
              'span[class="x1lliihq x193iq5w x6ikm8r x10wlt62 xlyipyv xuxw1ft"]', // 博主账号
              'div[class="x1a6qonq x6ikm8r x10wlt62 xj0a0fe x126k92a x6prxxf x7r5mf7"]', // 文案
              'span[class="x17qophe x10l6tqk x13vifvy"]', // 点赞数
              'span[class="x17qophe x10l6tqk x13vifvy"]', // 评论数
              'time[class="x1rg5ohu xnei2rj x2b8uid xuxw1ft"]', // 发布时间
            ]

            const authorElement = await visiblePost.$(selectors[0])
            const author = authorElement ? await page.evaluate((el) => el.textContent.trim(), authorElement) : "未知博主"
            console.log(`  [博主账号] => ${author}`)
            postData.platformAccount = author

            const captionElement = await visiblePost.$(selectors[1])
            if (!captionElement) {
              console.log("  [文案] 未找到，跳过该帖子")
              continue
            }

            const caption = await page.evaluate((el) => el.textContent.trim()?.replace(/翻译|翻譯|translation|translate|翻訳|terjemahan/g, ""), captionElement)
            if (isHandleList.includes(caption)) {
              // 已经处理过不再处理。跳过
              console.log("当前帖子已经处理过了。继续循环。下一个")
              continue
            }

            // 如果caption为空或者过短，可能是无效文案，跳过处理
            if (!caption || caption.length < 2) {
              console.log("  [文案] 文案内容为空或过短，跳过该帖子")
              continue
            }

            postData.caption = caption
            // 判断帖子是否处理过
            const hash1Text = CryptoJS.SHA1(postData.platformAccount + postData.caption).toString()
            console.log(`  [账号][文案] ${postData.caption} 哈希值: ${hash1Text}`)
            // 判断是否处理过。已处理过的不在处理
            if (isHandleList.includes(hash1Text)) {
              console.log("本地帖子已经处理过了，跳过")
              continue
            } else {
              const selectPostRes = await isPostCommented(
                {
                  sha1Hash: hash1Text,
                },
                {
                  headers: {
                    "Content-Type": "application/x-www-form-urlencoded",
                    "X-Platform": task.platformName,
                    "X-ScriptApp": "browser",
                    "X-Device-Id": task.deviceId,
                    "tenant-id": task.tenantId,
                  },
                }
              )
              console.log("  [是否已评论] =>", selectPostRes)
              if (selectPostRes?.data) {
                console.log("接口帖子已经处理过了，跳过")
                isHandleList.push(postData.caption)
                continue
              }
            }
            // 只有在确认帖子需要处理后，才进行滚动操作
            if (boundingBox) {
              // 在执行滚动前，先检查是否已经在底部
              const isAtBottom = await page.evaluate(() => {
                return document.documentElement.scrollTop + window.innerHeight >= document.documentElement.scrollHeight
              })

              if (!isAtBottom && !finished) {
                // 计算滚动位置，使其出现在视口中间
                await page.evaluate(({ x, y, height }) => {
                  window.scrollTo({
                    top: y + height / 2 - window.innerHeight / 2,
                    left: x,
                    behavior: "smooth", // 平滑滚动
                  })
                }, boundingBox)
                console.log("我在滑动页面 - 前往未处理帖子")
              } else {
                console.log("已经在底部，不再滚动")
              }
            }

            const dateElement = await visiblePost.$(selectors[4])
            const date = dateElement ? await page.evaluate((el) => el.textContent.trim(), dateElement) : "未知时间"
            postData.date = isPostTimeFrame(date, _timeFrame) || date
            console.log(`  [发布时间] => ${date}`)
            // 判断日期。只要近七天的。
            if (!isPostTimeFrame(date, _timeFrame)) {
              console.log(`[发布时间] 超过${timeOfText[Number(_timeFrame)]}范围，跳过该帖子`)
              finished = true
              break
            }

            // 记录打开新标签页前的滚动位置
            const beforeNewPageScrollPosition = await page.evaluate(() => window.scrollY)

            // 检查targetElement是否存在
            const targetElement = await visiblePost.$('div[class="x6s0dn4 xmixu3c x78zum5 x5yr21d x6ikm8r x10wlt62 xh8yej3"]')
            if (!targetElement) {
              console.log("  [详情页] 无法找到详情页链接元素，跳过该帖子")
              continue
            }

            // 创建一个新的 Promise 来等待新页面的打开
            const [newPage, impression_count] = await Promise.all([
              new Promise((resolve) => {
                // 设置超时
                const timeoutId = setTimeout(() => {
                  console.log("等待新页面创建超时")
                  resolve(null)
                }, 10000)

                // 监听新页面创建事件
                const handleNewPage = async (target) => {
                  clearTimeout(timeoutId)
                  const newPage = await target.page()
                  resolve(newPage)
                }

                browser.once("targetcreated", handleNewPage)
              }),
              new Promise((resolve) => {
                // 为曝光量请求添加超时时间，避免无限等待
                const timeoutId = setTimeout(() => {
                  console.log("获取曝光量超时，继续处理")
                  impressionHandled = true
                  resolve(0)
                }, 10000)

                let impressionHandled = false
                const handleImpressionResponse = async (response) => {
                  if (impressionHandled) return
                  if (response.url().includes("www.threads.net/graphql/query")) {
                    const request = response.request()
                    if (request.method() === "POST") {
                      try {
                        const contentType = response.headers()["content-type"] || ""
                        let responseBody
                        if (contentType.includes("application/json")) {
                          responseBody = await response.json()
                        } else {
                          responseBody = await response.text()
                        }
                        if (responseBody?.data?.media?.text_post_app_info?.impression_count) {
                          const impression_count = responseBody?.data?.media?.text_post_app_info?.impression_count
                          clearTimeout(timeoutId)
                          impressionHandled = true
                          resolve(impression_count)
                          return
                        }
                      } catch (error) {
                        console.log(`Error parsing request:`, error)
                      }
                    }
                  }
                }
                page.on("response", handleImpressionResponse)
              }),
              // 点击操作
              (async () => {
                try {
                  console.log("Control===1")
                  await new Promise((resolve) => setTimeout(resolve, 2000))

                  // 等待元素稳定
                  const initialBox = await targetElement.boundingBox()
                  await new Promise((resolve) => setTimeout(resolve, 500))
                  const finalBox = await targetElement.boundingBox()

                  if (initialBox && finalBox && initialBox.x === finalBox.x && initialBox.y === finalBox.y) {
                    console.log("Element is stable")
                  }

                  // 确保元素在视图中
                  await page.evaluate((element) => {
                    element.scrollIntoView({ behavior: "smooth", block: "center" })
                  }, targetElement)

                  // 等待滚动完成
                  await new Promise((resolve) => setTimeout(resolve, 500))

                  // 获取元素的位置
                  const box = await targetElement.boundingBox()
                  if (!box) {
                    throw new Error("Element not found or not visible")
                  }

                  // 计算点击位置（元素中心）
                  const x = box.x + box.width / 2
                  const y = box.y + box.height / 2

                  // 按下 Ctrl 键
                  await page.keyboard.down("Control")
                  console.log("Control===2")

                  // 确保键盘事件被捕获
                  await new Promise((resolve) => setTimeout(resolve, 100))

                  // 使用 mouse.click 进行点击
                  await page.mouse.click(x, y, { delay: 100 })
                  console.log("Control===3")

                  // 等待点击事件处理
                  await new Promise((resolve) => setTimeout(resolve, 100))

                  // 释放 Ctrl 键
                  await page.keyboard.up("Control")

                  // 等待新标签页创建
                  await new Promise((resolve) => setTimeout(resolve, 1000))
                } catch (error) {
                  console.error("Error during click operation:", error)
                  throw error
                }
              })(),
            ])

            // 检查新页面是否成功创建
            if (!newPage) {
              console.log("新页面创建失败，跳过当前帖子")
              continue
            }

            console.log("曝光量=====>", impression_count)
            postData.impression_count = impression_count
            // 等待新页面加载完成
            await newPage.waitForSelector("body") // 等待 body 加载完成
            // 切换到新页面
            await newPage.bringToFront() // 将新页面带到前端
            // 捕获新页面的接口数据
            const responseData = new Promise((resolve) => {
              // 为接口数据添加超时
              const responseTimeoutId = setTimeout(() => {
                console.log("获取接口数据超时，使用默认值")
                // 标记为已处理，防止重复处理
                postDataHandled = true
                resolve({
                  like_count: 0,
                  direct_reply_count: 0,
                  repost_count: 0,
                  reshare_count: 0,
                })
              }, 15000) // 15秒超时

              // 使用标志位控制是否已经处理过响应
              let postDataHandled = false

              // 响应处理函数
              const handlePostDataResponse = async (response) => {
                // 如果已经处理过或超时，直接返回
                if (postDataHandled) return

                if (response.url().includes("www.threads.net/graphql/query")) {
                  // 假设需要捕获的接口包含 'www.threads.net/graphql/query'
                  // 查询该请求的参数的variables
                  const request = response.request() // 获取请求对象
                  console.log(`=== Response Received ===`)
                  console.log(`URL: ${request.url()}`)
                  console.log(`Method: ${request.method()}`)
                  // 获取请求参数（仅 POST 请求有效）
                  if (request.method() === "POST") {
                    console.log(`Post Data: ${request.postData()}`)

                    // 获取响应数据
                    try {
                      // 解析 URL 参数或 JSON 数据
                      const params = new URLSearchParams(request.postData())
                      const variablesEncoded = params.get("variables")

                      if (!variablesEncoded) return

                      // 解码 variables 参数
                      const variables = JSON.parse(decodeURIComponent(variablesEncoded))
                      console.log("variables===>", variables)
                      // 判断是否包含 post_id
                      if (variables.post_id && /^\d+$/.test(variables.post_id)) {
                        console.log(`=== Matched Response ===`)
                        console.log(`URL: ${request.url()}`)
                        console.log(`Method: ${request.method()}`)
                        console.log(`Post Data:`, variables)

                        // 获取响应数据
                        const contentType = response.headers()["content-type"] || ""
                        let responseBody

                        if (contentType.includes("application/json")) {
                          responseBody = await response.json()
                        } else {
                          responseBody = await response.text()
                        }

                        // 配置postData
                        const postHttpData = {
                          like_count: responseBody?.data?.dynamicCountsData?.like_count || 0,
                          direct_reply_count: responseBody?.data?.dynamicCountsData?.text_post_app_info?.direct_reply_count || 0,
                          repost_count: responseBody?.data?.dynamicCountsData?.text_post_app_info?.repost_count || 0,
                          reshare_count: responseBody?.data?.dynamicCountsData?.text_post_app_info?.reshare_count || 0,
                        }

                        clearTimeout(responseTimeoutId) // 清除超时
                        // 标记为已处理，防止重复处理
                        postDataHandled = true
                        resolve(postHttpData) // 返回接口数据
                        return
                      }
                    } catch (error) {
                      console.log(`Error parsing request:`, error)
                    }
                  }
                }
              }

              // 添加响应处理监听器
              newPage.on("response", handlePostDataResponse)
            })

            // 获取接口数据
            const data = await responseData
            console.log("接口数据：", data)
            postData.like_count = data.like_count
            postData.direct_reply_count = data.direct_reply_count
            postData.repost_count = data.repost_count
            postData.reshare_count = data.reshare_count
            postData.followedCount = Number(followedCount) || 0
            console.log("当前帖子为：====>", postData)
            const params = {
              platformAccount: task.platformAccount,
              author: author.trim(),
              title: "",
              content: postData.caption?.trim()?.replace(/翻译|翻譯|translation|translate|翻訳|terjemahan/g, ""),
              viewNum: Number(postData.impression_count),
              likeNum: Number(postData.like_count),
              commentNum: Number(postData.direct_reply_count),
              isBotCommented: true,
              postDate: isPostTimeFrame(postData.date, _timeFrame) || "",
              commentTime: Date.now(),
            }
            console.log("请求参数：", params)
            // 判断一下曝光量和点赞量是否满足要求。如果满足直接评论
            if (postData.impression_count >= _amountOfExposure && postData.like_count >= _likeCount) {
              console.log("满足条件，开始评论")
              // 获取评论按钮进行点击
              const commentButton = await newPage.waitForSelector(".x6s0dn4:nth-child(2) > .x1i10hfl > .x6s0dn4", { timeout: 1000 * 15 })
              commentButton && (await commentButton.click())
              await fillPostContent(newPage, commentText)
              // 点击发布
              await submitPost(newPage)
              const saveRes = await savePostData(params, {
                headers: {
                  "X-Platform": task.platformName,
                  "X-ScriptApp": "browser",
                  "X-Device-Id": task.deviceId,
                  "tenant-id": task.tenantId,
                },
              })
              console.log("saveRes===>", saveRes)
              await new Promise((resolve) => setTimeout(resolve, 1000 * 2))

              // 更新本地缓存中的最后评论时间
              commentCycleStore.set(cacheKey, currentTime)
              console.log(`评论成功，已更新本地缓存的评论时间: ${new Date(currentTime).toLocaleString()}`)

              // 增加评论计数
              result.commentedCount++

              // 是否要置顶
              if (_topPost) {
                // 获取评论列表。看看是否有刚刚评论的内容。
                const commentSelector = `div[class="x1ypdohk x1n2onr6 xvuun6i x3qs2gp x1w8tkb5 x8xoigl xz9dl7a xsag5q8 x6bh95i x13fuv20 xt8cgyo"]`
                // 获取评论列表。看看是否有刚刚评论的内容。
                // 文案内容选择器
                const textSelector = `span[class="x1lliihq x1plvlek xryxfnj x1n2onr6 x1ji0vk5 x18bv5gf x193iq5w xeuugli x1fj9vlw x13faqbe x1vvkbs x1s928wv xhkezso x1gmr53x x1cpjm7i x1fgarty x1943h6x x1i0vuye xjohtrz xo1l8bm xp07o12 x1yc453h xat24cr xdj266r"]`
                // 更多操作选择器.xqcrz7y .x146dn1l .x1lliihq
                const moreBtnSelector = `.xqcrz7y .x146dn1l .x1lliihq`
                // 已发布a[class="x1i10hfl x1qjc9v5 xjbqb8w xjqpnuy xa49m3k xqeqjp1 x2hbi6w x13fuv20 xu3j5b3 x1q0q8m5 x26u7qi x972fbf xcfux6l x1qhh985 xm0m39n x9f619 x1ypdohk xdl72j9 x2lah0s xe8uvvx xdj266r x11i5rnm xat24cr x1mh8g0r x2lwn1j xeuugli xexx8yu x4uap5 x18d9i69 xkhd6sd x1n2onr6 x16tdsg8 x1hl2dhg xggy1nq x1ja2u2z x1t137rt x1q0g3np x1lku1pv x1rg5ohu x1a2a7pz x1lcm9me x1yr5g0i xrt01vj x10y3i5r xm4wzdf xwhw2v2 x87ps6o"]
                const publishedDivSelector = `a[class="x1i10hfl x1qjc9v5 xjbqb8w xjqpnuy xa49m3k xqeqjp1 x2hbi6w x13fuv20 xu3j5b3 x1q0q8m5 x26u7qi x972fbf xcfux6l x1qhh985 xm0m39n x9f619 x1ypdohk xdl72j9 x2lah0s xe8uvvx xdj266r x11i5rnm xat24cr x1mh8g0r x2lwn1j xeuugli xexx8yu x4uap5 x18d9i69 xkhd6sd x1n2onr6 x16tdsg8 x1hl2dhg xggy1nq x1ja2u2z x1t137rt x1q0g3np x1lku1pv x1rg5ohu x1a2a7pz x1lcm9me x1yr5g0i xrt01vj x10y3i5r xm4wzdf xwhw2v2 x87ps6o"]`
                // 循环找一分钟已发布
                const checkBox = await waitForSelectorWithInterval(newPage, publishedDivSelector, 1000, 1000 * 60)
                if (checkBox) {
                  checkBox.click()
                  // 最大查找次数
                  let maxFindCount = 0
                  let moreBtn = null
                  // 获取更多操作按钮
                  while (maxFindCount <= 10) {
                    console.log(`开始第${maxFindCount + 1}次寻找更多按钮`)
                    await new Promise((resolve) => setTimeout(resolve, 5000))
                    // 获取更多操作按钮
                    const commentSelector = `div[class="x1n2onr6 xvuun6i x3qs2gp x1w8tkb5 x8xoigl xsag5q8 xyamay9 x1sqbtui"]`
                    // 等待元素出现
                    await newPage.waitForSelector(commentSelector, { timeout: 1000 * 5 })
                    // 获取评论列表
                    const commentItems = await newPage.$$(commentSelector)
                    // 遍历过滤出dom文案和发布文案一致的元素
                    for (let index = 0; index < commentItems.length; index++) {
                      const commentItem = commentItems[index]
                      // 获取commentItem的子集span[class="x1lliihq x1plvlek xryxfnj x1n2onr6 x1ji0vk5 x18bv5gf xi7mnp6 x193iq5w xeuugli x1fj9vlw x13faqbe x1vvkbs x1s928wv xhkezso x1gmr53x x1cpjm7i x1fgarty x1943h6x x1i0vuye xjohtrz xo1l8bm xp07o12 x1yc453h xat24cr xdj266r"]文案
                      const commentComtentDom = await commentItem.$(
                        `span[class="x1lliihq x1plvlek xryxfnj x1n2onr6 x1ji0vk5 x18bv5gf xi7mnp6 x193iq5w xeuugli x1fj9vlw x13faqbe x1vvkbs x1s928wv xhkezso x1gmr53x x1cpjm7i x1fgarty x1943h6x x1i0vuye xjohtrz xo1l8bm xp07o12 x1yc453h xat24cr xdj266r"]`
                      )
                      // 获取commentComtentDom的文本
                      const commentContent = await (commentComtentDom && commentComtentDom.evaluate((el) => el.textContent.trim()))
                      // 判断是否为发布文案
                      // 去掉字符串里面的…
                      const commentContentTrim = commentContent?.trim().replace(/…|翻译|翻譯|translation|translate|翻訳|terjemahan/g, "")
                      console.log("commentText?.trim()", commentText?.trim())
                      console.log("commentContentTrim===>", commentContentTrim.trim())
                      console.log("commentText?.trim()?.includes(commentContentTrim)", commentText?.trim()?.includes(commentContentTrim.trim()))
                      if (
                        commentText
                          ?.trim()
                          ?.replace(/https:\/\/|http:\/\//, "")
                          .includes(commentContentTrim?.trim())
                      ) {
                        // 如果相同。直接获取更多按钮
                        moreBtn = await commentItem.$(`.x1a2a7pz:nth-child(2) .x146dn1l:nth-child(1) .x1lliihq:nth-child(1)`)
                        break
                      }
                    }
                    if (moreBtn) {
                      break
                    }
                  }
                  // 点击更多按钮
                  if (moreBtn) {
                    console.log("点击更多按钮")
                    await moreBtn.click()
                    await new Promise((resolve) => setTimeout(resolve, 1000 * 2))
                    const pinTopSelector = `div[class="x6s0dn4 x78zum5 x1szn6h9 x1n2onr6 x1qrby5j x1vjfegm xisnujt"]`
                    await newPage.waitForSelector(pinTopSelector, { timeout: 1000 * 15 })
                    const pinTopBtns = (await newPage.$$(pinTopSelector)) || []
                    await new Promise((resolve) => setTimeout(resolve, 1000 * 2))
                    // 过滤出文案为置顶的按钮
                    for (let index = 0; index < pinTopBtns.length; index++) {
                      const pinTopBtn = pinTopBtns[index]
                      const text = await pinTopBtn.evaluate((el) => el.textContent.trim())
                      console.log("按钮文本", text)
                      if (/置顶回复|置頂回覆/.test(text)) {
                        console.log("找到置顶按钮")
                        await pinTopBtn.click()
                        try {
                          // 获取是否有更换置顶的弹出框
                          const changePinTopSelector = `div.x18xmwgd:nth-child(1)`
                          await newPage.waitForSelector(changePinTopSelector, { timeout: 1000 * 5 })
                          const changePinTopBtn = await newPage.$(changePinTopSelector)
                          if (changePinTopBtn) {
                            console.log("找到置顶弹出框")
                            changePinTopBtn.click()
                          }
                        } catch (error) {
                          console.log("没有找到更换置顶按钮")
                        }
                      }
                    }
                  } else {
                    console.log("没有找到置顶按钮")
                  }
                }

                await new Promise((resolve) => setTimeout(resolve, 1000 * 5))
              }
            } else {
              // 不评论
              console.log("不满足条件，不评论")
            }
            // 添加到已处理的数据中
            isHandleList.push(postData.caption)
            console.log("已处理的数据：", isHandleList)
            postDataTotal.push(postData)
            lastHandlePost = postData.caption
            console.log("最后一条已处理的帖子：", lastHandlePost)

            // 标记为已处理了至少一篇新帖子
            processedAnyNewPost = true

            // 安全关闭新页面，防止页面未打开导致错误
            try {
              if (newPage && !newPage.isClosed()) {
                await newPage.close()
                // 确保将焦点切回主页面，但保持滚动位置
                await page.bringToFront()
                // 恢复之前的滚动位置
                await page.evaluate((position) => {
                  window.scrollTo({
                    top: position,
                    behavior: "instant", // 使用 instant 而不是 smooth 来避免滚动动画
                  })
                }, beforeNewPageScrollPosition)
              }
            } catch (error) {
              console.error("关闭新页面发生错误:", error.message)
              // 错误不影响主流程，继续执行
            }

            await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 2))
          } catch (error) {
            console.error(`处理第${index + 1}个帖子时发生错误:`, error.message)
            // 错误不影响下一个帖子的处理，继续循环
            continue
          }
        }

        // 检查是否在本轮循环中处理了任何新帖子
        const endingHandledCount = isHandleList.length
        if (endingHandledCount === startingHandledCount && !processedAnyNewPost) {
          console.log("本轮循环未处理任何新帖子，需要滚动加载更多内容")

          // 处理完一轮获取新的帖子列表前，保存当前滚动位置
          const beforeNewRoundScrollPosition = await page.evaluate(() => window.scrollY)

          // 记录无效滚动次数
          let ineffectiveScrollCount = 0
          const MAX_INEFFECTIVE_SCROLLS = 3 // 最多允许3次无效滚动

          // 修改滚动到底部的逻辑，确保滚动不会重置
          let isAtBottom = false
          // 记录当前已处理的文案数量
          const beforeScrollHandledCount = isHandleList.length

          // 记录滚动前的位置
          let beforeScrollToBottomPosition = await page.evaluate(() => window.scrollY)
          let foundNewPosts = false

          while (!finished && !isAtBottom && !foundNewPosts) {
            const isReachedBottom = await scrollToBottom(1000, page)

            // 短暂等待让页面加载新内容
            await new Promise((resolve) => setTimeout(resolve, 500))

            // 获取当前滚动位置
            const currentPosition = await page.evaluate(() => window.scrollY)

            // 检查滚动是否有效
            if (currentPosition <= beforeScrollToBottomPosition) {
              ineffectiveScrollCount++
              console.log(`无效滚动 ${ineffectiveScrollCount}/${MAX_INEFFECTIVE_SCROLLS}`)

              if (ineffectiveScrollCount >= MAX_INEFFECTIVE_SCROLLS) {
                console.log("连续多次滚动无效，认为已到底部")
                isAtBottom = true
              }
            } else {
              // 重置无效滚动计数器
              ineffectiveScrollCount = 0
              // 更新滚动前位置
              beforeScrollToBottomPosition = currentPosition
            }

            if (isReachedBottom) {
              isAtBottom = true
              console.log("已经到底了或无法继续向下滚动!")
            }

            // 滚动后获取新的帖子列表，检查是否有新的未处理文案
            let newPostList = await page.$$(postSelector)
            let hasNewPosts = false

            console.log(`滚动后检查是否有新的未处理帖子，列表长度: ${newPostList.length}`)

            // 定义文案选择器
            const captionSelector = 'div[class="x1a6qonq x6ikm8r x10wlt62 xj0a0fe x126k92a x6prxxf x7r5mf7"]' // 文案

            // 只检查可见的帖子
            for (const post of newPostList) {
              const box = await post.boundingBox()
              if (!box) continue // 跳过不可见的帖子

              // 获取文案
              const captionElement = await post.$(captionSelector)
              if (!captionElement) continue // 跳过没有文案的帖子

              const caption = await page.evaluate((el) => el.textContent.trim()?.replace(/翻译|翻譯|translation|translate|翻訳|terjemahan/g, ""), captionElement)
              if (!caption || caption.length < 2) continue // 跳过文案为空或太短的帖子

              // 检查是否已处理过
              if (!isHandleList.includes(caption)) {
                hasNewPosts = true
                console.log(`发现新的未处理帖子: "${caption.substring(0, 20)}..."，继续处理`)
                foundNewPosts = true // 标记发现了新帖子
                break
              }
            }

            // 如果没有新的未处理帖子，继续滚动或终止
            if (!hasNewPosts) {
              console.log(`滚动后未发现新的未处理帖子，已处理 ${isHandleList.length} 篇帖子，继续滚动`)
              // 如果已经到底，终止滚动
              if (isAtBottom) {
                console.log("已经滚动到底部且没有发现新帖子，终止循环")
                finished = true
              }
            } else {
              // 如果发现了新帖子，退出滚动循环，回到主循环处理这些新帖子
              console.log("发现新帖子，退出滚动循环，回到主循环处理新帖子")
              break
            }
          }

          // 如果到达底部且没有新帖子，标记为完成
          if (isAtBottom && !foundNewPosts) {
            console.log("滚动到底部且没有找到新帖子，标记为完成")
            finished = true
          }
        } else {
          console.log(`本轮循环成功处理了 ${endingHandledCount - startingHandledCount} 篇新帖子，继续处理下一轮`)
        }
      }
      console.log("帖子数据汇总===>：", postDataTotal)
      console.log("帖子数据汇总总数===>：", postDataTotal.length)
      result.success = true
      result.message =
        result.commentedCount > 0 ? `成功评论了 ${result.commentedCount} 条帖子，下次评论时间：${_runCycle === "1" ? "24小时后" : "下个时间段"}` : "执行完成，但没有找到符合条件的帖子进行评论"
    }
  } catch (error) {
    console.error("Error occurred during processing:", error)
    result.success = false
    result.message = `执行出错: ${error.message}`
  } finally {
    // page.close()
  }
  return result
}
async function scrollToBottom(step = 100, page) {
  const scrollResult = await page.evaluate(async (step) => {
    const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms))

    // 获取滚动前的位置
    const beforeScrollY = window.scrollY
    console.log("滚动前位置:", beforeScrollY)

    // 计算合理的滚动步长
    const scrollStep = step + Math.random() * step * 0.5 // 每次滚动 100-150px，减小随机性
    const scrollDelay = 50 + Math.random() * 100 // 每次滚动间隔 50-150ms，更流畅

    // 使用相对滚动，从当前位置滚动一定距离，而不是绝对位置
    window.scrollBy({
      top: scrollStep,
      behavior: "smooth", // 使用平滑滚动
    })

    await delay(scrollDelay)

    // 模拟偶尔停顿，但减少概率
    if (Math.random() < 0.1) {
      const pauseTime = 500 + Math.random() * 1000 // 0.5-1.5秒的停顿，缩短停顿时间
      await delay(pauseTime)
    }

    // 获取滚动后的位置，并确认滚动是否有效
    const afterScrollY = window.scrollY
    console.log("滚动后位置:", afterScrollY)

    // 计算滚动是否有效（是否真的向下滚动了）
    const scrolledEffectively = afterScrollY > beforeScrollY

    // 判断是否到底部
    const reachedBottom = document.documentElement.scrollTop + window.innerHeight >= document.documentElement.scrollHeight - 10 // 添加10px的容差

    return {
      reachedBottom,
      scrolledEffectively,
      beforePosition: beforeScrollY,
      afterPosition: afterScrollY,
    }
  }, step)

  // 记录滚动结果
  console.log(`滚动结果: 到达底部=${scrollResult.reachedBottom}, 有效滚动=${scrollResult.scrolledEffectively}, 位置变化=${scrollResult.beforePosition} -> ${scrollResult.afterPosition}`)

  // 如果滚动无效，可以认为已经到底
  if (!scrollResult.scrolledEffectively) {
    console.log("滚动无效，可能已经到底或遇到阻碍")
  }

  return scrollResult.reachedBottom
}
/**
 * 填写发帖文案
 * @param {Page} page - Puppeteer页面实例
 * @param {string} content - 帖子内容
 */
async function fillPostContent(page, content) {
  try {
    // 等待文本输入区域出现
    await page.waitForSelector('div[contenteditable="true"], textarea', { timeout: 10000 })

    // 尝试定位文本输入框
    const textArea = (await page.$('div[contenteditable="true"]')) || (await page.$("textarea"))

    if (textArea) {
      // 清空现有内容
      await textArea.click({ clickCount: 3 }) // 全选
      await page.keyboard.press("Backspace") // 删除

      // 输入新内容
      await textArea.type(content, { delay: 100 })
    } else {
      throw new Error("未找到文本输入区域")
    }
  } catch (error) {
    console.error("填写发帖文案时出错:", error)
    // 关闭这个页面
    await page.close()
    throw new Error("填写文案失败: " + error.message)
  }
}
/**
 * 提交发布帖子
 * @param {Page} page - Puppeteer页面实例
 */
async function submitPost(page) {
  try {
    // 外层容器选择器
    const outerSelector = 'div[class="x6s0dn4 x9f619 x78zum5 x15zctf7 x18r3tyq x1qughib x1p5oq8j xxbr6pl xwxc41k xbbxn1n xh8yej3"]'

    // 目标按钮的父级选择器
    const innerSelector = ".x2lah0s:nth-child(1) > .x9dqhi0"

    // 查找外层容器
    const outerElement = await page.$(outerSelector)
    if (!outerElement) {
      throw new Error("未找到外层发布按钮容器")
    }

    // 在外层容器中查找目标按钮
    const publishBtn = await outerElement.$(innerSelector)
    if (!publishBtn) {
      throw new Error("未找到发布提交按钮")
    }
    const rect = await publishBtn.boundingBox()
    await page.mouse.move(rect.x + rect.width / 2, rect.y + rect.height / 2)
    await page.mouse.down()
    await new Promise((resolve) => setTimeout(resolve, 100))
    await page.mouse.up()
  } catch (error) {
    console.error("提交发布帖子时出错:", error)
    throw new Error("提交发布失败: " + error.message)
  }
}
/**
 * 异步判断是否在运行条件中
 * @param {number} lastCommentTime 上次运行时间
 * @param {number} currentTime 当前时间
 * @param {Array} ranges 时间段数组（仅 _runCycle === "2" 时需要）
 * @param {object} commentCycleStore 本地缓存操作对象
 * @param {string} cacheKey 缓存键
 * @param {string} _runCycle 运行周期 "1"=每天, "2"=时间段
 * @param {boolean} onlyCheck 是否只判断不写入缓存，默认 false
 * @returns {Promise<false | string | true>}
 */
export async function isInConditionsAsync(lastCommentTime, currentTime, ranges, commentCycleStore, cacheKey, _runCycle, onlyCheck = false) {
  if (lastCommentTime) {
    const lastTimeObj = new Date(lastCommentTime)
    console.log(`上次评论时间: ${lastTimeObj.toLocaleString()}`)

    if (_runCycle === "1") {
      const hoursPassed = (currentTime - lastCommentTime) / (1000 * 60 * 60)
      console.log(`距离上次评论已经过去 ${hoursPassed.toFixed(2)} 小时`)

      if (hoursPassed < 24) {
        const msg = `未到达每日评论周期，还需等待 ${(24 - hoursPassed).toFixed(2)} 小时`
        console.log(msg)
        return msg
      } else {
        console.log("每日运行条件通过")
        if (!onlyCheck) {
          console.log("更新本地缓存中的最后评论时间")
          commentCycleStore.set(cacheKey, currentTime)
        }
        return false
      }
    }

    if (_runCycle === "2") {
      const lastDate = lastTimeObj.toLocaleDateString()
      const currentDate = new Date().toLocaleDateString()
      const lastHour = lastTimeObj.getHours()
      const lastMinute = lastTimeObj.getMinutes()
      const currentHour = new Date().getHours()
      const currentMinute = new Date().getMinutes()

      const getCurrentTimeSlot = (hour, minute) => {
        const currentTotalMinutes = hour * 60 + minute
        if (!ranges || ranges.length === 0) {
          return `${hour.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}`
        }

        for (const range of ranges) {
          const [startHour, startMinute] = range.startTime.split(":").map(Number)
          const [endHour, endMinute] = range.endTime.split(":").map(Number)
          const startTotalMinutes = startHour * 60 + startMinute
          const endTotalMinutes = endHour * 60 + endMinute

          if (currentTotalMinutes >= startTotalMinutes && currentTotalMinutes <= endTotalMinutes) {
            return `${range.startTime}-${range.endTime}`
          }
        }

        const fallback = `${hour.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}`
        console.log(`当前时间 ${fallback} 不在任何时间段内`)
        return fallback
      }

      const lastSlot = getCurrentTimeSlot(lastHour, lastMinute)
      const currentSlot = getCurrentTimeSlot(currentHour, currentMinute)

      console.log(`上次时间段: ${lastDate} ${lastSlot}, 当前时间段: ${currentDate} ${currentSlot}`)

      if (lastDate === currentDate && lastSlot === currentSlot) {
        const msg = `当前时间段 (${currentSlot}) 已执行过评论任务，等待下一个时间段`
        console.log(msg)
        return msg
      } else {
        console.log("时间段模式条件通过")
        if (!onlyCheck) {
          console.log("更新本地缓存中的最后评论时间")
          commentCycleStore.set(cacheKey, currentTime)
        }
        return false
      }
    }

    return true // 未知运行周期
  } else {
    console.log("首次运行评论任务，无需检查周期")
    if (!onlyCheck) {
      commentCycleStore.set(cacheKey, currentTime)
    }
    return false
  }
}

